/**
 * 
 */
package fr.utbm.gi.vi51.slizers.framework.agent;

import java.util.List;

import javax.vecmath.Point2i;

import org.janusproject.kernel.agent.Agent;
import org.janusproject.kernel.status.Status;

import fr.utbm.gi.vi51.slizers.framework.environment.Environment;
import fr.utbm.gi.vi51.slizers.framework.environment.Perception;
import fr.utbm.gi.vi51.slizers.pw.agent.action.CreatureActionInfluence;

/**
 * Abstract implementation of a agent with a situated body in an environment.
 * 
 * @author Tarik Belabbas
 * 
 */
public abstract class SituatedAgent< BodyType extends AgentBody > extends Agent
{
	/**
	 * Version number associated to the serializable class.
	 */
	private static final long	serialVersionUID	= -4872100957962240089L;

	/**
	 * The body of the agent.
	 */
	private BodyType			body				= null;

	/**
	 * Default constructor.
	 */
	public SituatedAgent()
	{
		
	}
	
	/**
	 * Create the body for the agent.
	 * 
	 * @param _environment the environment to create the body
	 * @return the agent body created
	 */
	protected abstract BodyType createBody( Environment _environment );
	
	/**
	 * Spawn a body for the agent, invoked by the environment.
	 * 
	 * @param _environment the environment to create the body
	 * @return the agent body created
	 */
	public BodyType spawnBody( Environment _environment )
	{
		if ( this.body == null )
		{
			this.body = createBody( _environment );
		}
		
		return this.body;
	}

	/**
	 * Returns the body of the agent.
	 * 
	 * @return the body of the agent
	 */
	public BodyType getBody()
	{
		return this.body;
	}

	/**
	 * Influences the body of the agent with an action influence.
	 * 
	 * @param _actionInfluence the influence for the action
	 */
	public void influenceBody( CreatureActionInfluence _actionInfluence )
	{
		getBody().influenceBody( _actionInfluence );
	}

	/**
	 * Returns the perceptions of the agent.
	 * 
	 * @return the perceptions of the agent
	 */
	public List< Perception > getPerceivedObjects()
	{
		return getBody().getPerceivedObjects();
	}
	
	/**
	 * Returns the position of the object.
	 * 
	 * @return the x-coordinate of the position of this object.
	 */
	protected int getX()
	{
		return this.body.getX();
	}

	/**
	 * Returns the position of the object.
	 * 
	 * @return the y-coordinate of the position of this object.
	 */
	protected int getY()
	{
		return this.body.getY();
	}

	/**
	 * Returns the position of the object.
	 * 
	 * @return the position of the object.
	 */
	protected Point2i getPosition()
	{
		return this.body.getPosition();
	}

	/**
	 * Returns the orientation of the object.
	 * 
	 * @return the orientation direction.
	 */
	protected Direction getDirection()
	{
		return this.body.getDirection();
	}
	
	/**
	 * Run the behavior of the situated agent.
	 * 
	 * @return the status of the execution, usually StatusFactory.ok( this ).
	 */
	@Override
	public abstract Status live();
}
